Um guia completo sobre Compartilhamento de Recursos de Origem Cruzada (CORS), abordando configuração, implicações de segurança e melhores práticas para desenvolvedores.
Compartilhamento de Recursos de Origem Cruzada (CORS): Configuração e Melhores Práticas de Segurança
No mundo do desenvolvimento web, a segurança é primordial. Um aspecto crítico da segurança web é gerenciar como páginas web de uma origem podem acessar recursos de uma origem diferente. É aqui que o Compartilhamento de Recursos de Origem Cruzada (CORS) entra em cena. O CORS é um recurso de segurança do navegador que restringe páginas web de fazerem requisições para um domínio diferente daquele que serviu a página. Esse mecanismo existe para impedir que sites maliciosos acessem dados sensíveis. Este artigo fornece um guia completo sobre o CORS, cobrindo sua configuração, implicações de segurança e melhores práticas.
Entendendo a Política de Mesma Origem
O CORS é construído sobre a base da Política de Mesma Origem, um mecanismo de segurança fundamental implementado pelos navegadores web. A política de mesma origem restringe páginas web de fazerem requisições para um domínio diferente daquele que serviu a página. Duas URLs são consideradas de mesma origem se tiverem o mesmo protocolo (ex: HTTP ou HTTPS), host (ex: example.com) e porta (ex: 80 ou 443). Por exemplo:
http://example.comehttp://example.com/pathsão da mesma origem.http://example.comehttps://example.comsão de origens diferentes (protocolos diferentes).http://example.comehttp://www.example.comsão de origens diferentes (hosts diferentes).http://example.com:80ehttp://example.com:8080são de origens diferentes (portas diferentes).
A política de mesma origem foi projetada para prevenir ataques de Cross-Site Scripting (XSS), onde um site malicioso injeta scripts em um site confiável para roubar dados do usuário ou realizar ações não autorizadas. Sem a política de mesma origem, um site malicioso poderia potencialmente acessar as informações da sua conta bancária se você estivesse logado no portal do seu banco online em outra aba.
O que é o Compartilhamento de Recursos de Origem Cruzada (CORS)?
Embora a política de mesma origem seja crucial para a segurança, ela também pode ser restritiva em cenários legítimos onde sites precisam acessar recursos de diferentes origens. Por exemplo, uma aplicação web hospedada em example.com pode precisar buscar dados de uma API hospedada em api.example.net. O CORS fornece um mecanismo para contornar a política de mesma origem de maneira controlada, permitindo que páginas web façam requisições de origem cruzada quando explicitamente autorizadas pelo servidor.
O CORS funciona adicionando cabeçalhos HTTP à resposta do servidor, indicando quais origens têm permissão para acessar o recurso. O navegador então verifica esses cabeçalhos e bloqueia a requisição se a origem da página web que está fazendo a requisição não for permitida.
Como o CORS Funciona: Os Cabeçalhos HTTP
O CORS depende de cabeçalhos HTTP específicos para facilitar requisições de origem cruzada. Aqui estão os principais cabeçalhos envolvidos:
1. Origin (Cabeçalho de Requisição)
O cabeçalho Origin é enviado pelo navegador em requisições de origem cruzada. Ele indica a origem (protocolo, host e porta) da página web que está fazendo a requisição. Por exemplo:
Origin: http://example.com
2. Access-Control-Allow-Origin (Cabeçalho de Resposta)
O cabeçalho Access-Control-Allow-Origin é o mais importante no CORS. Ele especifica quais origens têm permissão para acessar o recurso. Pode ter um dos seguintes valores:
- Uma origem específica: Por exemplo,
Access-Control-Allow-Origin: http://example.compermite apenas requisições dehttp://example.com. *(curinga):Access-Control-Allow-Origin: *permite requisições de qualquer origem. Isso deve ser usado com cautela, pois desativa efetivamente a política de mesma origem para aquele recurso.
Exemplo:
Access-Control-Allow-Origin: https://www.example.com
3. Access-Control-Allow-Methods (Cabeçalho de Resposta)
O cabeçalho Access-Control-Allow-Methods especifica os métodos HTTP (ex: GET, POST, PUT, DELETE) que são permitidos na requisição de origem cruzada. Isso é necessário para requisições preflight (explicado abaixo).
Exemplo:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
4. Access-Control-Allow-Headers (Cabeçalho de Resposta)
O cabeçalho Access-Control-Allow-Headers especifica os cabeçalhos HTTP que são permitidos na requisição de origem cruzada. Isso também é necessário para requisições preflight.
Exemplo:
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
5. Access-Control-Allow-Credentials (Cabeçalho de Resposta)
O cabeçalho Access-Control-Allow-Credentials especifica se o navegador deve incluir credenciais (ex: cookies, cabeçalhos de autorização) na requisição de origem cruzada. Pode ter um de dois valores: true ou false. Se true for definido, o cabeçalho Access-Control-Allow-Origin não pode ser definido como *. Ele deve ser uma origem específica.
Exemplo:
Access-Control-Allow-Credentials: true
6. Access-Control-Max-Age (Cabeçalho de Resposta)
O cabeçalho Access-Control-Max-Age especifica o número de segundos que o navegador pode armazenar em cache os resultados da requisição preflight. Isso pode melhorar o desempenho, reduzindo o número de requisições preflight.
Exemplo:
Access-Control-Max-Age: 3600
Requisições Simples vs. Requisições Preflight
O CORS distingue entre dois tipos de requisições de origem cruzada: requisições simples e requisições preflight.
Requisições Simples
Uma requisição simples é uma requisição que atende aos seguintes critérios:
- O método é
GET,HEADouPOST. - Se o método é
POST, o cabeçalhoContent-Typeé um dos seguintes:application/x-www-form-urlencoded,multipart/form-dataoutext/plain. - A requisição não define cabeçalhos personalizados (além daqueles definidos automaticamente pelo navegador).
Para requisições simples, o navegador envia a requisição diretamente para o servidor. O servidor então responde com os cabeçalhos CORS apropriados. Se a origem for permitida, o navegador processa a resposta. Caso contrário, o navegador bloqueia a resposta e lança um erro.
Requisições Preflight
Uma requisição preflight é enviada pelo navegador antes de fazer a requisição de origem cruzada real se a requisição não atender aos critérios para uma requisição simples. Isso geralmente acontece quando a requisição usa um método diferente de GET, HEAD ou POST, ou quando a requisição define cabeçalhos personalizados.
A requisição preflight é uma requisição OPTIONS que inclui os seguintes cabeçalhos:
Origin: A origem da página web que está fazendo a requisição.Access-Control-Request-Method: O método HTTP que será usado na requisição real.Access-Control-Request-Headers: Uma lista separada por vírgulas dos cabeçalhos personalizados que serão usados na requisição real.
O servidor então responde com os seguintes cabeçalhos:
Access-Control-Allow-Origin: A origem que tem permissão para acessar o recurso.Access-Control-Allow-Methods: Os métodos HTTP que são permitidos na requisição de origem cruzada.Access-Control-Allow-Headers: Os cabeçalhos HTTP que são permitidos na requisição de origem cruzada.Access-Control-Max-Age: O número de segundos que o navegador pode armazenar em cache os resultados da requisição preflight.
Se o servidor responder com os cabeçalhos CORS apropriados, o navegador prossegue com a requisição de origem cruzada real. Caso contrário, o navegador bloqueia a requisição e lança um erro.
Exemplos de Configuração do CORS
A implementação do CORS varia dependendo da tecnologia do lado do servidor que você está usando. Aqui estão alguns exemplos para linguagens e frameworks comuns do lado do servidor:
Node.js com Express
Usar o middleware cors é uma abordagem comum para configurar o CORS em Node.js com Express:
const express = require('express');
const cors = require('cors');
const app = express();
// Habilita o CORS para todas as origens
app.use(cors());
// Habilita o CORS para uma origem específica
// app.use(cors({ origin: 'http://example.com' }));
// Habilita o CORS com opções
// app.use(cors({
// origin: ['http://example.com', 'http://localhost:3000'],
// methods: ['GET', 'POST', 'PUT', 'DELETE'],
// allowedHeaders: ['Content-Type', 'Authorization'],
// credentials: true
// }));
app.get('/api/data', (req, res) => {
res.json({ message: 'Olá da API!' });
});
app.listen(3001, () => {
console.log('Servidor escutando na porta 3001');
});
Python com Flask
Você pode usar a extensão Flask-CORS para configurar o CORS no Flask:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# Habilita o CORS para todas as origens
CORS(app)
# Habilita o CORS para origens específicas
# CORS(app, origins=['http://example.com', 'http://localhost:3000'])
@app.route('/api/data')
def get_data():
return {'message': 'Olá da API!'}
if __name__ == '__main__':
app.run(port=3001)
Java com Spring Boot
O Spring Boot oferece várias maneiras de configurar o CORS. Uma abordagem é usar a anotação @CrossOrigin:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Origem específica
public class ApiController {
@GetMapping("/api/data")
public String getData() {
return "Olá da API!";
}
}
// Configuração global de CORS (usando WebMvcConfigurer):
// @Configuration
// public class CorsConfig implements WebMvcConfigurer {
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOrigins("http://example.com", "http://localhost:3000")
// .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// .allowedHeaders("Content-Type", "Authorization")
// .allowCredentials(true)
// .maxAge(3600);
// }
// }
PHP
Em PHP, você pode definir os cabeçalhos CORS diretamente no seu script:
<?php
header("Access-Control-Allow-Origin: http://example.com");
header("Content-Type: application/json");
$data = array("message" => "Olá da API!");
echo json_encode($data);
?>
Considerações de Segurança do CORS
Embora o CORS permita requisições de origem cruzada, é crucial entender as implicações de segurança e implementá-lo corretamente para evitar vulnerabilidades.
1. Evite Usar Access-Control-Allow-Origin: * em Produção
Usar o curinga * no cabeçalho Access-Control-Allow-Origin permite requisições de qualquer origem, desativando efetivamente a política de mesma origem para aquele recurso. Isso pode expor sua API a sites maliciosos que podem potencialmente roubar dados do usuário ou realizar ações não autorizadas. Em vez disso, especifique as origens exatas que têm permissão para acessar o recurso. Por exemplo, se sua aplicação web está hospedada em example.com e precisa acessar uma API hospedada em api.example.com, defina o cabeçalho como Access-Control-Allow-Origin: http://example.com.
Exemplo global: Imagine uma API de serviço financeiro definindo Access-Control-Allow-Origin: *. Um site malicioso poderia então fazer requisições para esta API em nome de um usuário logado, potencialmente transferindo fundos sem o conhecimento do usuário.
2. Valide o Cabeçalho Origin no Servidor
Mesmo que você especifique uma lista de origens permitidas, é importante validar o cabeçalho Origin no servidor para evitar que atacantes falsifiquem a origem. Um atacante poderia potencialmente enviar uma requisição com um cabeçalho Origin forjado para contornar as verificações do CORS. Para mitigar isso, compare o cabeçalho Origin com uma lista de origens confiáveis no lado do servidor. Se a origem não estiver na lista, rejeite a requisição.
Exemplo global: Considere uma plataforma de e-commerce. Um atacante poderia tentar imitar a Origin de uma loja legítima para acessar dados sensíveis de clientes da API da plataforma de e-commerce.
3. Tenha Cuidado com Access-Control-Allow-Credentials: true
Se você definir Access-Control-Allow-Credentials: true, o cabeçalho Access-Control-Allow-Origin não pode ser definido como *. Ele deve ser uma origem específica. Isso ocorre porque permitir credenciais de qualquer origem pode criar um risco de segurança, pois poderia permitir que sites maliciosos acessem dados do usuário se conseguirem enganar um usuário a visitar seu site enquanto o usuário também está logado no site alvo. Essa configuração é importante ao lidar com cookies ou cabeçalhos de autorização.
Exemplo global: Uma plataforma de mídia social que permite requisições de origem cruzada com credenciais requer um gerenciamento cuidadoso para evitar o acesso não autorizado às contas dos usuários.
4. Configure Adequadamente Access-Control-Allow-Methods e Access-Control-Allow-Headers
Permita apenas os métodos e cabeçalhos HTTP que são necessários para as requisições de origem cruzada. Se você só precisa permitir requisições GET e POST, não permita PUT, DELETE ou outros métodos. Da mesma forma, permita apenas os cabeçalhos específicos que sua aplicação precisa. Configurações excessivamente permissivas podem aumentar o risco de ataques.
Exemplo Global: Um sistema de CRM deve expor apenas os endpoints de API e cabeçalhos necessários para integrações de terceiros autorizadas, minimizando a superfície de ataque.
5. Use HTTPS para Comunicação Segura
Sempre use HTTPS para comunicação segura entre o navegador e o servidor. O HTTPS criptografa os dados transmitidos entre o navegador e o servidor, prevenindo espionagem e ataques man-in-the-middle. Usar HTTP pode expor dados sensíveis a atacantes, mesmo que o CORS esteja configurado corretamente.
Exemplo Global: Aplicações de saúde devem usar HTTPS para proteger os dados dos pacientes transmitidos entre diferentes origens.
6. Content Security Policy (CSP)
Embora não esteja diretamente relacionado ao CORS, a Content Security Policy (CSP) é outro mecanismo de segurança importante que pode ajudar a prevenir ataques XSS. A CSP permite que você defina uma lista de permissões de fontes das quais o navegador pode carregar recursos. Isso pode ajudar a impedir que atacantes injetem scripts maliciosos em seu site, mesmo que consigam contornar outras medidas de segurança.
Exemplo global: Instituições financeiras frequentemente empregam políticas de CSP rigorosas para limitar as fontes de conteúdo carregado em seus portais de banco online, reduzindo o risco de ataques XSS.
Problemas Comuns de CORS e Solução de Problemas
Erros de CORS podem ser frustrantes de depurar. Aqui estão alguns problemas comuns e como solucioná-los:
1. "O cabeçalho 'Access-Control-Allow-Origin' não está presente no recurso solicitado."
Este é o erro de CORS mais comum. Ele indica que o servidor não está retornando o cabeçalho Access-Control-Allow-Origin em sua resposta. Certifique-se de que o servidor está configurado para enviar os cabeçalhos CORS corretos para a origem da página web que está fazendo a requisição. Verifique novamente seu código do lado do servidor e arquivos de configuração.
2. "A resposta à requisição preflight não passa na verificação de controle de acesso: não possui status HTTP ok."
Este erro indica que a requisição preflight falhou. Isso pode acontecer se o servidor não estiver respondendo a requisições OPTIONS ou se o servidor estiver retornando um código de status de erro (ex: 404, 500) em resposta à requisição preflight. Certifique-se de que seu servidor está configurado para lidar com requisições OPTIONS e que está retornando um código de status 200 OK.
3. "A resposta à requisição preflight não passa na verificação de controle de acesso: o valor do cabeçalho 'Access-Control-Allow-Origin' na resposta não deve ser o curinga '*' quando o modo de credenciais da requisição é 'include'."
Este erro ocorre quando você está tentando enviar credenciais (ex: cookies) em uma requisição de origem cruzada e o cabeçalho Access-Control-Allow-Origin está definido como *. Como mencionado anteriormente, você não pode usar o curinga * ao enviar credenciais. Você deve especificar a origem exata que tem permissão para acessar o recurso.
4. Cache do Navegador
Os navegadores podem armazenar em cache as respostas do CORS, o que pode levar a um comportamento inesperado se a configuração do CORS mudar. Para evitar problemas de cache, defina o cabeçalho Cache-Control na resposta como no-cache, no-store ou max-age=0. Você também pode usar o cabeçalho Access-Control-Max-Age para controlar por quanto tempo o navegador armazena em cache os resultados da requisição preflight.
Alternativas ao CORS
Embora o CORS seja a maneira padrão de habilitar requisições de origem cruzada, existem algumas alternativas que você pode considerar em certos cenários:
1. JSON com Padding (JSONP)
JSONP é uma técnica que usa a tag <script> para contornar a política de mesma origem. O JSONP funciona envolvendo os dados JSON em uma chamada de função JavaScript. O navegador então executa a função JavaScript, passando os dados JSON como argumento. O JSONP é mais simples de implementar do que o CORS, mas tem algumas limitações. Ele só suporta requisições GET e é menos seguro que o CORS.
2. Proxy Reverso
Um proxy reverso é um servidor que fica na frente do seu servidor de API и encaminha as requisições para ele. O proxy reverso pode ser configurado para adicionar os cabeçalhos CORS necessários à resposta, escondendo efetivamente as requisições de origem cruzada do navegador. Essa abordagem pode ser útil se você não tiver controle sobre o servidor da API ou se quiser simplificar a configuração do CORS.
Conclusão
O Compartilhamento de Recursos de Origem Cruzada (CORS) é um mecanismo de segurança crucial que permite que páginas web acessem recursos de diferentes origens de maneira controlada. Entender como o CORS funciona e implementá-lo corretamente é essencial para construir aplicações web seguras e confiáveis. Seguindo as melhores práticas descritas neste artigo, você pode gerenciar eficazmente o CORS e proteger suas APIs de acesso não autorizado.
Lembre-se de sempre priorizar a segurança ao configurar o CORS. Evite usar curingas, valide o cabeçalho Origin e use HTTPS para comunicação segura. Ao tomar essas precauções, você pode garantir que suas aplicações web estejam protegidas contra ataques cross-site.
Este guia completo fornece uma base sólida для entender o CORS. Sempre consulte a documentação oficial da sua tecnologia específica do lado do servidor para obter as informações mais atualizadas e as melhores práticas. Mantenha-se informado sobre as ameaças de segurança emergentes e adapte sua configuração do CORS de acordo.